package com.rainbow.support.half.message.handler;

import com.rainbow.common.core.toolkit.ContextHolder;
import com.rainbow.common.core.toolkit.SpringBeanUtil;
import com.rainbow.support.half.message.entity.HalfMessagePayload;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.lang.NonNull;
import java.util.Date;
import java.util.Objects;
import java.util.Optional;

/**
 * RocketMq消息处理工具类
 * 提供消息生产者和消费者,统一处理逻辑,存储日志,验证信息,基于消费日志的幂等性统一工具类
 * @author rainbow
 */
public class MessageToolHandler implements BaseHalfMsgHandler{


    /**
     * 本地事务处理后,存储生产者消息日志
     * @param producer 生产者参数
     * @param message  源消息信息
     * @return 本地事务存储结果
     */
    public boolean saveProducerLog(@NonNull HalfMessagePayload producer, @NonNull String message) {
        String insertSql = "INSERT INTO rocket_mq_producer_log(branch_id,global_id,origin_body,remark,category,endpoint,chainpath,expandtag,reservetag,create_time,creator,logic_delete) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)";
        int total = Objects.requireNonNull(SpringBeanUtil.getBean(JdbcTemplate.class)).update(insertSql, producer.getBranchId(), producer.getGlobalId(), message, producer.getRemark(), producer.getCategory(), producer.getEndpoint(), producer.getChainpath(), producer.getExpandtag(), producer.getReservetag(), new Date(), ContextHolder.getUserId(), false);
        return ObjectUtils.isNotEmpty(total) && total > 0;
    }

    /**
     * 检查事务状态
     * @param branchId 分支事务id
     * @return  本地事务执行结果
     */
    public boolean checkTransactionStatus(@NonNull String branchId){
        Integer total=SpringBeanUtil.getBean("jdbcTemplate", JdbcTemplate.class).queryForObject(
                "select count(*) as total from rocket_mq_producer_log where logic_delete=false and branch_id = ?",
                Integer.class,
                branchId);
        return ObjectUtils.isNotEmpty(total) && total > 0;
    }

    /**
     * 根据业务唯一键,快速查询海量数据,帮忙控制生产者幂等性
     * 针对半事务生产者在生成分支事务id(唯一键生成)时,
     * 协助生产者做幂等处理工具
     * @param category 业务类型
     * @param expandtag 唯一业务参数
     * @return  参数唯一键检测出来结果
     */
    public boolean checkUniqueProducerByCategory(@NonNull String category,@NonNull String expandtag){
        if(StringUtils.isEmpty(category)||StringUtils.isEmpty(expandtag)){
            return false;
        }
        Integer total=SpringBeanUtil.getBean("jdbcTemplate", JdbcTemplate.class).queryForObject(
                "select count(*) as total from rocket_mq_producer_log where logic_delete=false and category = ? and expandtag = ?",
                Integer.class,
                category,
                expandtag);
        return ObjectUtils.isNotEmpty(total) && total > 0;
    }

    /**
     * MQ消费者,存储消费事务日志
     * @param payload 消息载体
     * @param message 消息主体
     * @return 存储消费事务日志
     */
    public boolean saveConsumerLog(@NonNull HalfMessagePayload payload, @NonNull String message) {
        String consumerUserId= Optional.ofNullable(payload.getCreator()).orElse(ContextHolder.getUserId());
        Date consumerTime=Optional.ofNullable(payload.getCreateTime()).orElse(new Date());
        String insertSql = "INSERT INTO rocket_mq_consumer_log(branch_id,global_id,origin_body,create_time,creator,logic_delete) VALUES (?,?,?,?,?,?)";
        int total = Objects.requireNonNull(SpringBeanUtil.getBean(JdbcTemplate.class)).update(insertSql, payload.getBranchId(), payload.getGlobalId(), message, consumerTime,consumerUserId , false);
        return ObjectUtils.isNotEmpty(total) && total > 0;
    }

    /**
     * MQ事务消费者,检查消息主体分支事务id,是否已经存在
     * @param branchId 消息主体分支事务id
     * @return 检查事务状态
     */
    public boolean checkBranchId(@NonNull String branchId) {
        Long total = Objects.requireNonNull(SpringBeanUtil.getBean(JdbcTemplate.class)).queryForObject(
                "select count(*) as total from rocket_mq_consumer_log where logic_delete=false and branch_id = ?",
                Long.class,
                branchId);
        return ObjectUtils.isNotEmpty(total) && total > 0;
    }

}
